package pl.edu.pw.polygen.db.dao;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.dozer.DozerBeanMapper;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.Alias;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.stereotype.Repository;

import pl.edu.pw.polygen.beans.ProjectBean;
import pl.edu.pw.polygen.beans.UserBean;
import pl.edu.pw.polygen.db.dao.generic.GenericDaoImpl;
import pl.edu.pw.polygen.db.entieties.Project;
import pl.edu.pw.polygen.db.entieties.User;

@Repository("projectDao")
public class ProjectDaoImpl extends GenericDaoImpl<Project, Long> implements
		ProjectDao {

	@Autowired
	private DozerBeanMapper mapper;

	public boolean isExisting(final ProjectBean projectBean) {
		final Project project = mapper.map(projectBean, Project.class);
		return getHibernateTemplate().execute(new HibernateCallback<Boolean>() {
			public Boolean doInHibernate(Session session)
					throws HibernateException, SQLException {
				Criteria criteria = session.createCriteria(Project.class)
						.add(Restrictions.eq("user", project.getUser()))
						.add(Restrictions.eq("name", project.getName()));
				List<User> projects = criteria.list();
				if (projects != null && projects.size() > 0) {
					return true;
				} else {
					return false;
				}
			}
		});
	}

	public ProjectBean saveProject(ProjectBean projectBean) {
		Project project = mapper.map(projectBean, Project.class);
		update(project);
		projectBean = mapper.map(project, ProjectBean.class);
		return projectBean;
	}

	public ProjectBean createNewProject(ProjectBean projectBean) {
		Project project = mapper.map(projectBean, Project.class);
		save(project);
		projectBean = mapper.map(project, ProjectBean.class);
		return projectBean;
	}

	public List<ProjectBean> findAllByUser(UserBean userBean) {
		final User user = mapper.map(userBean, User.class);
		return getHibernateTemplate().execute(
				new HibernateCallback<List<ProjectBean>>() {
					public List<ProjectBean> doInHibernate(Session session)
							throws HibernateException, SQLException {
						Criteria criteria = session
								.createCriteria(Project.class)
								.add(Restrictions.eq("user", user))
								.setResultTransformer(
										Criteria.DISTINCT_ROOT_ENTITY);
						List<ProjectBean> projectBeans = new ArrayList<ProjectBean>();
						List<Project> projects = criteria.list();
						for (Project project : projects) {
							projectBeans.add(mapper.map(project,
									ProjectBean.class));
						}
						return projectBeans;
					}
				});
	}

	public ProjectBean findProject(Long id) {
		Project project = getById(id);
		return mapper.map(project, ProjectBean.class);
	}

	public ProjectBean findProject(final String projectName, final Long userId) {
		return getHibernateTemplate().execute(
				new HibernateCallback<ProjectBean>() {
					public ProjectBean doInHibernate(Session session)
							throws HibernateException, SQLException {
						Criteria criteria = session
								.createCriteria(Project.class)
								.createAlias("user", "u")
								.add(Restrictions.eq("u.id", userId))
								.add(Restrictions.eq("name", projectName));
						Project project = (Project) criteria.uniqueResult();
						return mapper.map(project, ProjectBean.class);
					}
				});
	}

	public void delete(ProjectBean projectBean) {
		Project project = mapper.map(projectBean, Project.class);
		delete(project);
	}

}
